#include "GY_GraphicsImage.h"
#include <QBrush>
#include <QPen>
#include <QFile>
#include <QtMath>

GY_GraphicsImage::GY_GraphicsImage(const QString &guid, QGraphicsItem *parent)
    :GY_BasicsGraphicsObject(guid,this,parent)
{
    //图元类型
    GY_Object::setUserData(GY_ENUM::ClassType,QVariant("Image"));
    initializationPropertyInfo();
    QMap<QVariant,QPointF> editPoints = {
        {"Point",m_PropertyInfoMap["Size"].propertyValue.toPointF()}
    };
    QPointF positionPoint = m_PropertyInfoMap["Position"].propertyValue.toPointF();
    this->setEditPointF(editPoints);
    this->setCenterPointF(positionPoint);
    updateImage();
}

bool GY_GraphicsImage::updatePositionPoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>()){
        return false;
    }
    //移动整个图形，以便移动开始绘画点
    this->setPos(value.toPointF());
    QPointF mousePoint = this->mapFromScene(value.toPointF());
    m_PropertyInfoMap[name].propertyValue = mousePoint;
    this->setEditPointF("Point",this->mapFromScene(m_PropertyInfoMap["Size"].propertyValue.toPointF()+value.toPointF()));
    //设置中心点，基础图形
    this->setCenterPointF(mousePoint);
    updateImage();
    return true;
}

bool GY_GraphicsImage::updateSizePoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>()){
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateImage();
    this->setEditPointF("Point",this->mapFromScene(value.toPointF()+this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF())));
    return true;
}

bool GY_GraphicsImage::updatePoint(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap["Size"].propertyValue=(value.value<QPointF>())-this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    updateImage();
    this->setEditPointF(name,this->mapFromScene(value.value<QPointF>()));
    return true;
}

bool GY_GraphicsImage::updateRotationAngle(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>()){
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateImage();
    return true;
}

bool GY_GraphicsImage::updateIndex(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QString>()){
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    QFile file(value.toString());
    if(!file.exists()) {
        return false;
    }
    QImage image(value.toString());//获取图片路径
//    m_PropertyInfoMap["Size"].propertyValue = QPointF(image.width(),image.height());
    this->setEditPointF("Point",this->mapFromScene(QPointF(image.width(),image.height())+this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF())));
    updateImage();
    return true;
}

bool GY_GraphicsImage::updateAlphaValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<int>() && (value < 0 || value > 255)){
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateImage();
    return true;
}

bool GY_GraphicsImage::updateRealSize(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>() && value == false){
        return false;
    }
    QString index = m_PropertyInfoMap["Index"].propertyValue.toString();
    QPixmap image(index);
    //获取编辑点坐标
    QPointF positionPoint = m_PropertyInfoMap["Position"].propertyValue.toPointF();
    QPointF sizePoint = m_PropertyInfoMap["Size"].propertyValue.toPointF();
    //若为true，图片将恢复至初始大小且禁用sizePoint拖动
    if(value == true)
    {
        //获取图片的宽高值
        qreal width = image.width();
        qreal height = image.height();
        //若图片比例不协调，图片将恢复至等比例
        if(name.endsWith("Size"))
        {
            //重新设置sizePoint
            sizePoint.setX(positionPoint.x()+width);
            sizePoint.setX(positionPoint.y()+height);
//            m_PropertyInfoMap["Size"].propertyValue=sizePoint;
        }
    }
    m_PropertyInfoMap[name].propertyValue=value;

    updateImage();
    return true;
}
/**
 * @brief GY_GraphicsImage::updateProportionalSize
 * @param name
 * @param value
 * @return
 */
bool GY_GraphicsImage::updateProportionalSize(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>()){
        return false;
    }

    QPixmap image;
    //若为true，图片将恢复至等比例且只能按等比例缩放
    if(value == true)
    {
        //获取图片的宽高值
        qreal width = image.width();
        qreal height = image.height();
        //计算图片实际宽高比例
        qreal proportionReal = width/height;
        //获取sizePoint坐标
        QPointF sizePoint = m_PropertyInfoMap["Size"].propertyValue.toPointF();
        //计算图片当前宽高比例
        qreal proportionNow = sizePoint.x()/sizePoint.y();
        //若图片比例不协调，图片将恢复至等比例且只能按等比例缩放
        if(proportionNow != proportionReal)
        {
            sizePoint.setX(image.width()*proportionReal);
            sizePoint.setY(image.height()*proportionReal);
        }
    }
    //若为false，图片可根据sizePoint拖动按任意比例缩放
    else
    {
        return true;
    }

    m_PropertyInfoMap[name].propertyValue=value;
    return true;
}

void GY_GraphicsImage::updateImage()
{
    QString index = m_PropertyInfoMap["Index"].propertyValue.toString();
    if(index.isEmpty())
    {
        return;
    }
    QImage imagePath(index);//获取图片路径
    QPointF positionPoint = m_PropertyInfoMap["Position"].propertyValue.toPointF();
    QPointF sizePoint = m_PropertyInfoMap["Size"].propertyValue.toPointF();
    if(abs(sizePoint.x()) < 1){
        sizePoint.setX(1);
        m_PropertyInfoMap["Size"].propertyValue = sizePoint;
        this->setEditPointF("Point",this->mapFromScene(sizePoint+this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF())));
    }
    if(abs(sizePoint.y()) < 1){
        sizePoint.setY(1);
        m_PropertyInfoMap["Size"].propertyValue = sizePoint;
        this->setEditPointF("Point",this->mapFromScene(sizePoint+this->mapToScene(m_PropertyInfoMap["Position"].propertyValue.toPointF())));
    }
    int alphaValue = m_PropertyInfoMap["AlphaValue"].propertyValue.toInt();
    QImage mirroredImage;//用于修正图片的横向与纵向的变量
    QPixmap image;//QPixmap类型的变量
    QPainterPath path;
    path.addRect(positionPoint.x(),positionPoint.y(),sizePoint.x(),sizePoint.y());//绘制矩形边框
    //第一象限
    if(sizePoint.x() > positionPoint.x() && sizePoint.y() > positionPoint.y())
    {
        mirroredImage = imagePath.mirrored(false,true);//图片的横向与纵向都需要修正
        image = QPixmap::fromImage(mirroredImage).scaled(sizePoint.x(),sizePoint.y());//QImage转为QPixmap
    }
    //sizePoint移动到第二象限
    else if(sizePoint.x() < positionPoint.x() && sizePoint.y() > positionPoint.y())
    {
        mirroredImage = imagePath.mirrored(true,true);//图片的横向与纵向都需要修正
        image = QPixmap::fromImage(mirroredImage).scaled(-sizePoint.x(),sizePoint.y());//QImage转为QPixmap
    }
    //sizePoint移动到第三象限
    else if(sizePoint.x() < positionPoint.x() && sizePoint.y() < positionPoint.y())
    {
        mirroredImage = imagePath.mirrored(true,false);//图片的横向与纵向都需要修正
        image = QPixmap::fromImage(mirroredImage).scaled(-sizePoint.x(),-sizePoint.y());//QImage转为QPixmap
    }
    //sizePoint移动到第四象限
    else if(sizePoint.x() > positionPoint.x() && sizePoint.y() < positionPoint.y())
    {
        mirroredImage = imagePath.mirrored(false,false);//图片的横向与纵向都需要修正
        image = QPixmap::fromImage(mirroredImage).scaled(sizePoint.x(),-sizePoint.y());
    }else{//用于容错==
        mirroredImage = imagePath.mirrored(false,true);//图片的横向与纵向都需要修正
        image = QPixmap::fromImage(mirroredImage).scaled(sizePoint.x(),sizePoint.y());//QImage转为QPixmap
    }

    //设置图片透明度（已实现）
    QPixmap temp(image.size());//temp用于表示已设置透明度后的image
    temp.fill(Qt::transparent);
    QPainter p1(&temp);//p1用于绘制temp
    p1.setCompositionMode(QPainter::CompositionMode_Source);
    p1.drawPixmap(positionPoint.x(),positionPoint.y(),image);
    p1.setCompositionMode(QPainter::CompositionMode_DestinationIn);
    p1.fillRect(temp.rect(),QColor(0,0,0,alphaValue));//QColor中第四个参数设置透明度
    p1.end();

    this->setPath(path);
//    QBrush brush(temp);
    QBrush brush = this->brush();
    brush.setTexture(temp);//填充矩形边框内容为已设置透明度后的图片
    this->setBrush(brush);
    this->setPen(Qt::NoPen);//去掉矩形边框的颜色

    this->setRotation(m_PropertyInfoMap["RotationAngle"].propertyValue.toDouble());//旋转图片（已实现）
}

void GY_GraphicsImage::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap["ObjectName"].setConnect();

    GY_PropertyInfo IsVisible(this);
    IsVisible.propertyName = "IsVisible";
    IsVisible.propertyValue = true;
    IsVisible.updateType = Update|OrdinaryAttributes;
    IsVisible.propertyType = BoolPropertyType;
    IsVisible.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateIsVisible;
    m_PropertyInfoMap.insert("IsVisible",IsVisible);
    m_PropertyInfoMap["IsVisible"].setConnect();

    GY_PropertyInfo position(this);
    position.propertyName = "Position";
    position.propertyValue = QPointF(0,0);
    position.updateType = Update|MoveUpdate|PointOfRelative;
    position.propertyType = PointPropertyType;
    position.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updatePositionPoint;
    m_PropertyInfoMap.insert("Position",position);
    m_PropertyInfoMap["Position"].setConnect();

    GY_PropertyInfo rotationAngle(this);
    rotationAngle.propertyName = "RotationAngle";
    rotationAngle.propertyValue = qreal(0);
    rotationAngle.updateType = Update|OrdinaryAttributes;
    rotationAngle.propertyType = QrealPropertyType;
    rotationAngle.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateRotationAngle;
    m_PropertyInfoMap.insert("RotationAngle",rotationAngle);
    m_PropertyInfoMap["RotationAngle"].setConnect();

    GY_PropertyInfo index(this);
    index.propertyName = "Index";
//    index.propertyValue = "../PopElements/Tables/Images/AlphaBall.png";
    index.propertyValue = QString();
    index.updateType = Update|OrdinaryAttributes;
    index.propertyType = QStringPropertyType;
    index.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateIndex;
    m_PropertyInfoMap.insert("Index",index);
    m_PropertyInfoMap["Index"].setConnect();

    GY_PropertyInfo alphaValue(this);
    alphaValue.propertyName = "AlphaValue";
    alphaValue.propertyValue = int(255);
    alphaValue.updateType = Update|OrdinaryAttributes;
    alphaValue.propertyType = IntPropertyType;
    alphaValue.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateAlphaValue;
    m_PropertyInfoMap.insert("AlphaValue",alphaValue);
    m_PropertyInfoMap["AlphaValue"].setConnect();

    GY_PropertyInfo realSize(this);
    realSize.propertyName = "RealSize";
    realSize.propertyValue = true;
    realSize.updateType = Update|OrdinaryAttributes;
    realSize.propertyType = BoolPropertyType;
    realSize.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateRealSize;
    m_PropertyInfoMap.insert("RealSize",realSize);
    m_PropertyInfoMap["RealSize"].setConnect();

    GY_PropertyInfo proportionalSize(this);
    proportionalSize.propertyName = "ProportionalSize";
    proportionalSize.propertyValue = false;
    proportionalSize.updateType = Update|OrdinaryAttributes;
    proportionalSize.propertyType = BoolPropertyType;
    proportionalSize.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateProportionalSize;
    m_PropertyInfoMap.insert("ProportionalSize",proportionalSize);
    m_PropertyInfoMap["ProportionalSize"].setConnect();

    QImage image("../PopElements/Tables/Images/AlphaBall.png");
    GY_PropertyInfo size(this);
    size.propertyName = "Size";
    size.propertyValue = QPointF(image.width(),image.height());
    size.updateType = Update|OrdinaryAttributes;
    size.propertyType = PointPropertyType;
    size.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updateSizePoint;
    m_PropertyInfoMap.insert("Size",size);
    m_PropertyInfoMap["Size"].setConnect();

    GY_PropertyInfo pointPropertyInfo(this);
    pointPropertyInfo.propertyName="Point";
    pointPropertyInfo.propertyValue=QPointF(image.width(),image.height());
    pointPropertyInfo.updateType = NotUpdate;
    pointPropertyInfo.propertyType = PointPropertyType;
    pointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_GraphicsImage::updatePoint;
    m_PropertyInfoMap.insert(pointPropertyInfo.propertyName,pointPropertyInfo);
    m_PropertyInfoMap[pointPropertyInfo.propertyName].setConnect();
}

QPointF GY_GraphicsImage::precalculatedPosition(const QPointF &centerPoint, const double radius, const double angele)
{
    qreal radian=qDegreesToRadians(angele); //弧度
    QPointF resultPoint;
    resultPoint.setX(cos(radian)*radius);
    resultPoint.setY(sin(radian)*radius);
    resultPoint+=centerPoint;
    return resultPoint;
}
